package se.webbzon.oschi01.worldobject.appearance;

import javax.media.j3d.Geometry;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.TriangleStripArray;
import javax.vecmath.Point3d;
import javax.vecmath.TexCoord2f;

import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;

public class CubeAppearance3D extends SimpleAppearance3D {
	
	// The geometry model of the cube
	private static final Geometry model = createModel(1,1,1,false);
	
	// The geometry model of the back-faced cube
	private static final Geometry modelBackfaced = createModel(1,1,1,true);

	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new WorldObjectCubeAppearance. The center of
	 * the cube will be placed in the origin and all sides
	 * of the cube has a size equal to 1. **/
	public CubeAppearance3D() {
		this(0,0,false);
	}
	
	/** Creates a new WorldObjectCubeAppearance. The center of
	 * the cube will be placed in the origin and all sides
	 * of the cube has a size equal to 1. See WorldObjectSimpleAppearance 
	 * for full description of the attributes renderingOrder and 
	 * simpleAppearanceProperties. The appearance may be back-faced. **/
	public CubeAppearance3D(int renderingOrder, int simpleAppearanceProperties, boolean backfaced) {
		super(renderingOrder,simpleAppearanceProperties,backfaced ? modelBackfaced : model);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Creates the geometry model. **/
	private static Geometry createModel(	double width, 
											double height, 
											double depth,
											boolean backfaced) {
		double w = width/2, h = height/2, d = depth/2;
		TriangleStripArray ta = new TriangleStripArray(16,
											GeometryArray.COORDINATES +
											GeometryArray.NORMALS + 
											GeometryArray.TEXTURE_COORDINATE_2,
											new int[] {8,8});
		
		// Create the corners the of the cube
		Point3d tlf = new Point3d(-w,h,d);
		Point3d trf = new Point3d(w,h,d);
		Point3d tlb = new Point3d(-w,h,-d);
		Point3d trb = new Point3d(w,h,-d);
		Point3d blf = new Point3d(-w,-h,d);
		Point3d brf = new Point3d(w,-h,d);
		Point3d blb = new Point3d(-w,-h,-d);
		Point3d brb = new Point3d(w,-h,-d);
		
		// Generate texture coordinates
		TexCoord2f tl = new TexCoord2f(0,1);
		TexCoord2f tr = new TexCoord2f(1,1);
		TexCoord2f bl = new TexCoord2f(0,0);
		TexCoord2f br = new TexCoord2f(1,0);
		
		// Create cube parts (top, back, bottom and left, front, right)
		final Point3d[] part1, part2; 
		final TexCoord2f[] texCoord1, texCoord2;
		if (backfaced) {
			final Point3d[] p1 = {blf,brf,blb,brb,tlb,trb,tlf,trf};
			final Point3d[] p2 = {blb,tlb,blf,tlf,brf,trf,brb,trb};
			final TexCoord2f[] tc1 = {tl,tr,bl,br,tl,tr,bl,br};
			final TexCoord2f[] tc2 = {br,tr,bl,tl,br,tr,bl,tl};
			part1 = p1;
			part2 = p2;
			texCoord1 = tc1;
			texCoord2 = tc2;
		} else {
			final Point3d[] p1 = {tlf,trf,tlb,trb,blb,brb,blf,brf};
			final Point3d[] p2 = {brb,trb,brf,trf,blf,tlf,blb,tlb};
			final TexCoord2f[] tc1 = {bl,br,tl,tr,bl,br,tl,tr};
			final TexCoord2f[] tc2 = {bl,tl,br,tr,bl,tl,br,tr};
			part1 = p1;
			part2 = p2;
			texCoord1 = tc1;
			texCoord2 = tc2;
		}

		
		ta.setCoordinates(0, part1);
		ta.setCoordinates(8, part2);
		ta.setTextureCoordinates(0, 0, texCoord1);
		ta.setTextureCoordinates(0, 8, texCoord2);
		
		// Generate normals
		final GeometryInfo g = new GeometryInfo(ta);
		final NormalGenerator ng = new NormalGenerator();
		ng.generateNormals(g);
					
		return g.getGeometryArray();
	}
	

}
